package com.feature.core.rabbitmq;

import org.springframework.amqp.rabbit.connection.CachingConnectionFactory.ConfirmType;
import org.springframework.amqp.rabbit.core.CorrelationDataPostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnsCallback;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
import org.springframework.core.Ordered;

public class RabbitMqPropertiesBeanPostProcessor implements BeanPostProcessor, Ordered {

	@Autowired
	private ConfirmCallback confirmCallback;
	@Autowired
	private ReturnsCallback returnsCallback;
	@Autowired
	private CorrelationDataPostProcessor TraceIdCorrelationDataPostProcessor;

	@Override
	public int getOrder() {
		return Ordered.LOWEST_PRECEDENCE;
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if (bean instanceof RabbitProperties) {
			RabbitProperties properties = (RabbitProperties) bean;
			// 当消息成功投递到交换机，但没有被路由到任何队列时，RabbitMQ 可以通过 publisher-returns 机制返回一个回执给生产者，告知生产者该消息未能成功进入队列。
			properties.setPublisherReturns(true);
			// 消息发送到broke后，会触发回调
			properties.setPublisherConfirmType(ConfirmType.CORRELATED);
			// 当前最大允许空闲的最大通道（channel）数
			properties.getCache().getChannel().setSize(50);
			RabbitProperties.SimpleContainer config = properties.getListener().getSimple();
			config.setConcurrency(3);
			config.setMaxConcurrency(3);
			config.setPrefetch(50);
		}
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean instanceof RabbitTemplate) {
			RabbitTemplate rabbitTemplate = (RabbitTemplate) bean;
			// 消息发送到broke后，会触发回调
			rabbitTemplate.setConfirmCallback(confirmCallback);
			// 当消息成功投递到交换机，但没有被路由到任何队列时的回调
			rabbitTemplate.setReturnsCallback(returnsCallback);
			// 发送前处理
			rabbitTemplate.setCorrelationDataPostProcessor(TraceIdCorrelationDataPostProcessor);
		}
		return bean;
	}

}
